package com.gitee.l0km.xthrift.mq;

import java.util.Date;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.gitee.l0km.xthrift.mq.json.Iso8601DateCodec;

import static com.google.common.base.Preconditions.checkState;

/**
 * RPC请求消息封装
 * @author guyadong
 * @since 1.4.0
 *
 */
public class Envelope implements Cloneable{
	/** 请求响应频道，用于服务端向请求端返回RPC调用结果 */
	private String ack;
	/**
	 * 消息发送时间
	 */
	@JSONField(deserializeUsing = Iso8601DateCodec.class,serializeUsing = Iso8601DateCodec.class)
	protected Date sendTime;
	/** 对于异常，是否只输出简要错误信息，为{@code true}只输出 Throwable 的message字段的错误信息 */
	private Boolean thinError;
	/** [JSON] RPC请求/服务端响应数据 */
	private String body;
	/** {@link SimplemqDispatcher} 内部使用字段 */
	private long processStartTimeMillis;
	protected volatile JSONArray bodyArray;
	public Envelope() {
	}
    private Envelope(String ack, Date sendTime, String body) {
		this.ack = ack;
		this.sendTime = sendTime;
		this.body = body;
	}
	private Envelope(byte[] body, int offset, int length) {
    	this.body = new String(body,offset,length);
    	this.sendTime = new Date();
    }
	public long processStartTimeMillis() { return processStartTimeMillis; }

    public void processStartTimeMillis(long processStartTimeMillis)
    {
        this.processStartTimeMillis = processStartTimeMillis;
    }
    protected Envelope buildBody() {
    	JSONArray array = bodyArray();
    	setBody(JSON.toJSONString(array));
    	return this;
    }
    protected JSONArray bodyArray() {
    	if(null == bodyArray) {
    		synchronized (this) {
    			if(null == bodyArray) {
    				if (null != body) {
    					bodyArray = JSON.parseArray(body);
    				}
    			}
    		}
    	}
		checkState(bodyArray != null, "UNINITIALIZED field 'bodyArray'");
		checkState(bodyArray.size() == 5, "INVALID field 'bodyArray',5 size required");
		return bodyArray;
    }
    void bodyArray(JSONArray bodyArray) {
		this.bodyArray = bodyArray;
	}
    int seqid() {
    	return bodyArray().getIntValue(3);
    }
	int type() {
		return bodyArray().getIntValue(2);
	}
	String name() {
		return bodyArray().getString(1);
	}
	JSONObject content() {
		return JSON.parseObject(bodyArray().getString(4));
	}
	public static Envelope create(byte[] body, int offset, int length) {
		return new Envelope(body, offset, length);
	}
	@Override
	public Envelope clone()  {
		return new Envelope(ack, sendTime, body);
	}
	public String getAck() {
		return ack;
	}
	public void setAck(String ack) {
		this.ack = ack;
	}
	public Date getSendTime() {
		return sendTime;
	}
	public void setSendTime(Date sendTime) {
		this.sendTime = sendTime;
	}
	public Boolean getThinError() {
		return thinError;
	}
	public void setThinError(Boolean thinError) {
		this.thinError = thinError;
	}
	public String getBody() {
		return body;
	}
	public void setBody(String body) {
		this.body = body;
	}
}
